home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-01-07 | 51.0 KB | 1,356 lines | [TEXT/MPS ] |
- {
-
- Sample Source Code by Jack A. Littleton
-
- Example List Manager Application--TextList
- ------------------------------------------
-
- TextList.p -- Pascal source code for PTextList
- This file and all files in this package are copyright © 1989 by
- Jack A. Littleton, All rights reserved.
- Version 1.0 - December 3, 1989
-
- READ THE FILE SampleTextList.txt BEFORE CONTINUING!!!!
-
- This package includes:
- TextList.p -- This file
- TextList.c -- C source code
- TextList.r -- Rez source code for all TextList applications
- PTextList.r -- Pascal-specific Rez source code
- CTextList.r -- C-specific Rez source code
- PTextList.make -- Makefile for Pascal TextList application
- CTextList.make -- Makefile for C TextList application
-
- SampleTextList.txt -- Documentation for this package
-
- ABOUT TextList.p:
- This is the Pascal source code for PTextList, a Pascal implementation of
- an application that uses the List Manager. This implementation uses the
- only List Definition (LDEF) that is supplied with the system (LDEF #0),
- which can handle only text in the cells.
-
- The application handles multiple windows with a single list in each window.
- The list has both vertical and horizontal scroll bars. The cell size, font,
- and font size. A "List"
- menu allows you to set flags that affect how the list reacts to mouse
- clicks (the selFlags field in the ListHandle). The items that are set in
- the List menu do not take affect until you create a new list. When a new
- window is created, the application looks at which items in the List menu
- have been selected, and creates the list with those characteristics. Note
- that changes in the List menu do not affect previously created lists. This
- means that you can have several different lists open with different
- characteristics, allowing you to see the differences.
-
- The "Edit" menus allows cut/paste, but not through normal scrap techniques.
- Cells can be cut/pasted from one window to another, but not from PTextList
- to another application. This was implemented to show how to get, set and
- clear data from a cell.
-
- Find is supported in the "File" menu. This uses the LSearch procedure to
- find a match in the list.
-
- The windows and list support growing and zooming.
-
- Other important notes on implementation are given in the documentation for
- the appropriate routine.
-
- A NOTE: This is just an example of a program that uses the List Manager. It
- is not meant to be a full-blown application, and may not be suitable as
- a template for a new application. It is just meant to show as many List
- Manager routines as possible. In fact, this program was written as
- research for a programming tutorial and was never planned as a application.
- }
-
- program PTextList;
-
- USES MemTypes, { memory interface }
- QuickDraw, { interface to QuickDraw routines }
- OSIntf, { interface to the operating system }
- ToolIntf, { interface to the toolbox }
- PackIntf; { interface to package manager }
-
- CONST
- { Menu resource constants }
- NumMenus = 5; { The number of menus }
- AppleMenu = 1111; { Menu Resource Id for apple menu }
- AppleID = 1; { Index ID for apple menu }
-
- FileMenu = 1112; { Menu Resource Id for file menu }
- FileID = 2; { Index ID for file menu }
- NewItem = 1; { Index ID for "New" item }
- CloseItem = 2; { Index ID for "Close" item }
- AddItem = 3; { Index ID for "Add Row" item }
- DeleteItem = 4; { Index ID for "Delete Row" item }
- FindItem = 5; { Index ID for "Find…" item }
- Quit = 6; { Index ID for "Quit" item }
-
- EditMenu = 1113; { Resource ID for "Edit" menu }
- EditID = 3; { Index ID for "Edit" menu }
- UndoItem = 1; { Index ID for "Undo" item--not used }
- CutItem = 3; { Index ID for "Cut" item }
- CopyItem = 4; { Index ID for "Copy" item }
- PasteItem = 5; { Index ID for "Paste" item }
- ClearItem = 6; { Index ID for "Clear" item }
- SClipItem = 8; { Index ID for "Show Clipboard" item }
-
- ListMenu = 1114; { Resource ID for "List" menu }
- ListID = 4; { Index ID for "List" menu }
- OneSelItem = 1; { Index ID for "One Selection Only" item }
- DragWOShItem = 2; { Index ID for "Drag Without Shift" item }
- NoDJointItem = 3; { Index ID for "No Disjoint Selections" item }
- NoExtendItem = 4; { Index ID for "Don't Extend" item }
- NoExpandItem = 5; { Index ID for "Don't Expand as Rects" item }
- UseSenseItem = 6; { Index ID for "Use Sense" item }
- NoHliteItem = 7; { Index ID for "Don't Hilite Empty Cells" item }
-
- CellMenu = 1115; { Resource ID for "Cell" menu }
- CellID = 5; { Index ID for "Cell" menu }
- IndentItem = 1; { Index ID for "Indentation…" item }
- CSizeItem = 2; { Index ID for "Cell Size…" item }
- FSizeItem = 4; { Index ID for "Font Size…" item }
-
- FontSMenu = 1; { Resource ID for "Font" sub-menu }
-
- { Dialog/Alert box constants }
- cellDlog = 128; { Res ID for Cell Size/Indentation dialog }
- fontSDlog = 129; { Res ID for Find dialog }
- findDlog = 130; { Res ID for Font Size/Cells per Col dialog }
- aboutDlog = 1112; { Res ID for "About…" dialog }
-
- { String resource constants }
- theStrList = 128; { Res ID of string list }
- indentInd = 1; { Index ID for "Indentation" }
- vertInd = 2; { Index ID for "vertical" }
- horizInd = 3; { Index ID for "horizontal" }
- cSizeInd = 4; { Index ID for "Cell Size" }
-
- theWind = 1113;
-
- TYPE
- MenuListType = ARRAY [1..numMenus] OF MenuHandle;
-
- DocumentPeek = ^DocumentRecord;
- DocumentRecord = RECORD
- docWindow: WindowRecord;
- docList: ListHandle;
- END;
-
- VAR
- gDragArea: Rect; { Area where window can be dragged }
- gGrowArea: Rect; { Minimum size a window can be shrunk to }
- gActvWindow: WindowPtr; { Holds the pointer to the active window }
- gWindInfo: DocumentPeek; { Information about active window }
- gMenuItem: MenuListType; { An array of menu handles }
- gEvents: EventRecord; { The event record queue }
- gFinished: BOOLEAN; { Set to true when app finishes }
- gClipboard: Str255; { Private scrap for list }
- gClipLen: INTEGER; { Length of scrap }
- gFontSMenu: MenuHandle; { Font submenu handle }
- gFontName: Str255; { Name of current font }
- gFontItem: INTEGER; { Item ID of current font in font menu }
- gFontSize: INTEGER; { Size of current font }
- gNumWind: INTEGER; { Number of windows open }
-
- PROCEDURE DoNew; FORWARD;
-
- {
- # Initialize -- Initialize toolbox managers, menus and global variables
- #
- # Called by -- Main
- #
- # Description -- First, the application's heap zone is expanded and a block
- # of master pointers are allocated, then the toolbox managers are
- # initialized. Then the menus are called from the resource fork
- # and inserted into the menu bar. The "Font" menu is initialized
- # next by looking for the defualt font in the font menu. If the
- # font is not found, then the applicationFont is used instead.
- # Finally, the global variables are defined, and a new window
- # is displayed.
- }
- PROCEDURE Initialize;
-
- VAR
- i: INTEGER; { FOR loop control variable }
- menuID: INTEGER; { FOR loop control variable-used to find default font }
- dfltString: Str255; { The name of the default font }
- theString: Str255; { Font name returned by GetItem }
- numItems: INTEGER; { Number of items in "Font" menu }
- screenArea: Rect; { Size of the screen }
- screenPort: GrafPtr; { Returned by GetWMgrPort }
-
- BEGIN
- MaxApplZone;
- MoreMasters; { Get a block of master pointers }
- InitGraf(@thePort); { Initialize QuickDraw }
- InitFonts; { Initialize Font Manager }
- InitCursor; { Initialize Cursor (to arrow) }
- InitWindows; { Initialize Window Manager }
- InitMenus; { Initialize Menu Manager }
- TEInit; { Initialize TextEdit }
- InitDialogs(NIL); { Initialize Dialog Manager }
-
- FlushEvents(everyEvent,0); { Empty the event queue in case there were events there }
- GetWMgrPort(screenPort); { Set up the grafPort for all windows }
- SetPort(screenPort); { Keep the screen port on standby }
- screenArea := screenBits.bounds; { Get the size of this Mac's screen }
- WITH screenArea DO
- BEGIN
- SetRect(gDragArea,5, { This sets the area in which a window can be drug around }
- 25, { in. The references to right and bottom refer to the }
- Right-5, { record screenArea, derived from screenBits.bounds. This }
- Bottom-10); { keeps a mininum amount of window on the screen. }
- SetRect(gGrowArea,65, { Set the area where the window can grow into--it manages }
- 65, { to keep the window big enough so that the close and }
- Right-5, { zoom boxes are still visible. }
- Bottom-10);
- END;
-
- menuID := 1111; { The first menu's ID (the apple menu) }
- FOR i := 1 to NumMenus DO { Put all the menus in the menu bar }
- BEGIN
- gMenuItem[i] := GetMenu(menuID); { Get the menu from the resource manager }
- menuID := menuID + 1; { Increment the menu ID for the next menu }
- InsertMenu(gMenuItem[i],0); { Put the menu in the menu bar }
- END;
- AddResMenu(gMenuItem[AppleID],'DRVR'); { Get DRVR resources and put them in apple menu }
- gFontSMenu := GetMenu(FontSMenu); { Get the font sub-menu }
- AddResMenu(gFontSMenu, 'FONT'); { Get FONT resources and put them in the font menu }
- InsertMenu(gFontSMenu, -1); { Put the menu in the hierarchical menu area }
-
- numItems := CountMItems(gFontSMenu); { Get the number of items in the font menu }
- dfltString := 'Courier'; { Set default string }
- FOR i := 1 TO numItems DO { Keep looping until the default is found }
- BEGIN
- GetItem(gFontSMenu, i, theString);
- IF (EqualString(theString, dfltString, false, false)) THEN
- BEGIN
- CheckItem(gFontSMenu, i, true); { When the font is found, check it }
- gFontItem := i; { And initialize font global variables }
- gFontName := theString;
- END;
- END;
- DrawMenuBar; { Draw the menu bar }
- gActvWindow := nil; { Initialize global variables }
- gFontSize := 10;
- gFinished := false;
- gNumWind := 0;
- DoNew; { Get a new window }
- END;
-
- {
- # DoAboutBox -- Show dialog box with program information
- #
- # Called by -- DoAppleMenu
- #
- # Description -- Displays a dialog box, usually containing a picture that
- # gives information about the program. The dialog terminates
- # after the user clicks in the dialog.
- }
-
- PROCEDURE DoAboutBox;
-
- VAR
- doneDialog: BOOLEAN; { True if done with dialog }
- doDialog: DialogPtr; { Pointer to "about..." dialog }
- itemHit: INTEGER; { Returned by ModalDialog }
- thisPort: WindowPtr; { Graf port that is active when DoAboutBox is started }
-
- BEGIN
- doneDialog := FALSE; { Initialize the close dialog flag }
- doDialog := GetNewDialog(aboutDlog,NIL,
- POINTER(-1)); { Get the dialog box for the "about..." Window }
- GetPort(thisPort);
- SetPort(doDialog);
-
- REPEAT
- ModalDialog(NIL,itemHit); { Find which item was hit }
- CASE itemHit OF
- 1: doneDialog := TRUE; { If it was the picture, then quit }
-
- END; {case}
- UNTIL doneDialog;
-
- DisposDialog(doDialog); { Get rid of the dialog from screen and memory }
- HiliteMenu(0); { Unhighlight the menu }
- SetPort(thisPort); { Reset the dialog box font back to system font }
- END;
-
- {
- # DoAppleMenu -- An item was selected from the Apple (DA) menu
- #
- # Called by -- HandleMenuSelect
- #
- # Description -- There are two cases that need to be checked. If the itemID
- # passed as a parameter is 1, then call the DoAboutBox routine.
- # If the item ID is not one, then it is assumed that a Desk
- # Accessory was selected, and the DA should be opened. Note that
- # item 2 should be a dashed line that is disabled; therefore
- # itemID should never be 2.
- }
- PROCEDURE DoAppleMenu(itemID: INTEGER); { itemID = menu item number }
-
- VAR
- result: INTEGER; { result returned by GetDeskAcc--ignored }
- dAName: Str255; { Name of item selected-passed to OpenDeskAcc }
-
- BEGIN
- IF itemID = 1 THEN { If the about... item was picked, then }
- BEGIN { bring up the about box }
- DoAboutBox;
- END
- ELSE
- BEGIN { Otherwise, a desk accessory was picked }
- GetItem(gMenuItem[AppleID],itemID,dAName); { Get the name of the DA picked }
- result := OpenDeskAcc(dAName); { And open it }
- HiliteMenu(0); { Unhilite the menu }
- END;
- END; {DoAppleMenu}
-
- {
- # DoUnhilite -- Dim menu items when no list is present
- #
- # Called by -- DoClose (only when last window is closed)
- #
- # Description -- This routine dims menu items that can cause errors when
- # selected with no list present (i.e. any menu item that calls a
- # routine that expects a valid ListHandle)
- }
- PROCEDURE DoUnhilite;
-
- BEGIN
- DisableItem(gMenuItem[FileID], CloseItem); { Disable the "Close" menu item }
- DisableItem(gMenuItem[FileID], AddItem); { Disable the "Add Row" menu item }
- DisableItem(gMenuItem[FileID], DeleteItem); { Disable the "Delete Row" item }
- DisableItem(gMenuItem[FileID], FindItem); { Disable the "Find…" menu item }
- END;
-
- {
- # DoHilite -- Hilite menu items when a new list is created
- #
- # Called by -- DoNew (when no windows were present before DoNew call)
- #
- # Description -- This routines hilites the menu items dimmed by DoUnhilite
- # when a new window is created and it is the only window (i.e.
- # gNumWind = 0 before window was created)
- }
- PROCEDURE DoHilite;
-
- BEGIN
- EnableItem(gMenuItem[FileID], CloseItem); { Enable the "Close" menu item }
- EnableItem(gMenuItem[FileID], AddItem); { Enable the "Add Row" menu item }
- EnableItem(gMenuItem[FileID], DeleteItem); { Enable the "Delete Row" item }
- EnableItem(gMenuItem[FileID], FindItem); { Enable the "Find…" menu item }
- END;
-
- {
- # DoNew -- Create a new window and list
- #
- # Called by -- Initialize and DoFileMenu
- #
- # Description -- This routine allocates space for a new document record,
- # which is used in the wStorage parameter in the GetNewWindow
- # call. A new window is then created. If one or more windows
- # are present before the new window is created, the window size
- # is scaled down to allow windows behind the new window to be
- # visible. After scaling, the window is assigned a name in the
- # format : Untitled—<window number>, and then the window is
- # finally drawn.
- #
- # LIST MANAGER SPECIFICS:
- # ---- ------- ---------
- # Setting selFlags -- Before the list is created, each of the items in the
- # List menu is looked at to see if the user has selected that
- # item. If the item is checked, the constant representing that
- # flag is added to a flag constant that is later added to the
- # selFlags field in the ListHandle.
- #
- # Creating the list -- After the menu items have been scanned, a new list is
- # created with the List Manager routine LNew. RView is the
- # enclosing rectangle of the list, which is the same as the
- # window the list is in, except for a 15 pixel margin on the
- # bottom and right sides of the window to allow space for the
- # scroll bars. DataBounds is the number of cells the list is
- # initialized with.
- #
- # Drawing the list -- Once the window and list have been drawn, the List
- # manager routine LDoDraw is called, which draws the list when
- # necessary.
- }
- PROCEDURE DoNew;
-
- VAR
- fNum: INTEGER; { The font number used for the list }
- theMark: Char; { Returned by GetItemMark }
- flags: SignedByte; { Flags for the ListHandle }
- numStr: Str255; { String version of window number }
- windTitle: Str255; { Title of the new window }
- rView: Rect; { Size of the initial list }
- dataBounds: Rect; { Number of cells in initial list }
- cSize: Point; { Size of the cells in the list }
- windRec: Ptr; { Pointer to window storage }
-
- BEGIN
- windRec := NewPtr(sizeof(DocumentRecord)); { Allocate space for a document record }
- gActvWindow := GetNewWindow(theWind, windRec, WindowPtr(-1)); { Get a new window }
- gActvWindow^.portRect.top := gActvWindow^.portRect.top + (gNumWind * 20); { Shrink the top left part of the window }
- gActvWindow^.portRect.left := gActvWindow^.portRect.left + (gNumWind * 20); { so other windows are partially visible }
- IF gNumWind = 0 THEN { If this is the only window, then hilite }
- DoHilite; { the necessary menu items }
- gNumWind := gNumWind + 1; { Increment the number of windows }
- NumToString(LONGINT(gNumWind), numStr);
- SetWTitle(gActvWindow, CONCAT('Untitled—',numStr)); { Create the window title }
- gWindInfo := DocumentPeek(gActvWindow); { Get the document record pointer }
- GetFNum(gFontName, fNum); { Get the font number of the current font }
- gActvWindow^.txFont := fNum; { Set the current font }
- gActvWindow^.txSize := gFontSize; { And set the global var }
- SetPort(gActvWindow); { Set the port to our new window }
- rView := gActvWindow^.portRect; { Create the rView rectangle for the LNew call }
- rView.right := rView.right - 15; { Remember to allow enough space for the }
- rView.bottom := rView.bottom - 15; { list's scroll bars }
- ShowWindow(gActvWindow); { Make the window visible }
- SetRect(dataBounds, 0, 0, 10, 1); { Set the number of default cells }
- SetPt(cSize, 100, 16); { Set the default cell size }
-
- flags := 0; { Initialize the flags }
- GetItemMark(gMenuItem[ListID], 1, theMark);
- IF (theMark = CHR(checkMark)) THEN { Is the lOnlyOne flag set? }
- flags := flags + lOnlyOne; { If so, add it to the flags }
- GetItemMark(gMenuItem[ListID], 2, theMark);
- IF (theMark = CHR(checkMark)) THEN { Is the lExtendDrag flag set? }
- flags := flags + lExtendDrag; { If so, add it to the flags }
- GetItemMark(gMenuItem[ListID], 3, theMark);
- IF (theMark = CHR(checkMark)) THEN { Is the lNoDisjoint flag set? }
- flags := flags + lNoDisjoint; { If so, add it to the flags }
- GetItemMark(gMenuItem[ListID], 4, theMark);
- IF (theMark = CHR(checkMark)) THEN { Is the lNoExtend flag set? }
- flags := flags + lNoExtend; { If so, add it to the flags }
- GetItemMark(gMenuItem[ListID], 5, theMark);
- IF (theMark = CHR(checkMark)) THEN { Is the lNoRect flag set? }
- flags := flags + lNoRect; { If so, add it to the flags }
- GetItemMark(gMenuItem[ListID], 6, theMark);
- IF (theMark = CHR(checkMark)) THEN { Is the lUseSense flag set? }
- flags := flags + lUseSense; { If so, add it to the flags }
- GetItemMark(gMenuItem[ListID], 7, theMark);
- IF (theMark = CHR(checkMark)) THEN { Is the lNoNilHilite flag set? }
- flags := flags + lNoNilHilite; { If so, add it to the flags }
- gWindInfo^.docList := LNew(rView, dataBounds, cSize, 0,
- gActvWindow, true, false, true, true); { Create the new list }
- gWindInfo^.docList^^.selFlags := flags; { Set the selFlags field }
- LDoDraw(true, gWindInfo^.docList); { Allow drawing }
- END;
-
- {
- # DoClose -- Handle closing a window and disposing of its contents
- #
- # Called by -- DoFileMenu and HandleMouseDown
- #
- # Description -- This routine is called when "Close" is selected from the
- # "File" menu, or the mouse is clicked in the go away region of
- # the window. Any contents of the window should be handled
- # (i.e. disposed) before the window is closed. Before doing any
- # closing, the windowKind field should be checked. If it is
- # negative, the window to be closed belongs to a desk accessory.
- # When this happens, call CloseDeskAcc and pass the value in
- # windowKind. If a window is closed, and no other windows belong
- # to the application, the gNumWind variable is set to zero, and
- # the DoUnhilite procedure is called to dim the necessary menu
- # items.
- #
- # LIST MANAGER SPECIFICS
- # ---- ------- ---------
- # Disposing of the list -- Before closing the window, you need to call
- # LDispose to get rid of the list.
- }
- PROCEDURE DoClose;
-
- VAR
- testWindow: WindowPtr; { The active window }
- whatWindow: DocumentPeek; { The active window's window record }
-
- BEGIN
- testWindow := FrontWindow; { Get the active window }
- whatWindow := DocumentPeek(testWindow); { Coerce the window record }
- IF whatWindow^.docWindow.windowKind > 0 THEN { If it is an application window then }
- BEGIN
- LDispose(whatWindow^.docList); { Get rid of the list }
- CloseWindow(FrontWindow); { Get rid of the window }
- gActvWindow := FrontWindow; { Set the active window to the frontmost window }
- IF gActvWindow = NIL THEN { If there are no windows then }
- BEGIN
- gNumWind := 0; { Reset the window counter }
- DoUnhilite; { Dim the necessary menus }
- END
- ELSE { Otherwise, there are windows open }
- BEGIN
- SelectWindow(gActvWindow); { Select the active window }
- gWindInfo := DocumentPeek(gActvWindow); { Get the new Document Record }
- END
- END
- ELSE { If the window being closed was a DA window }
- CloseDeskAcc(whatWindow^.docWindow.windowKind); { Then close the desk accessory }
- HiliteMenu(0);
- END;
-
- {
- # DoQuit -- Stop the application
- #
- # Called by -- DoFileMenu
- #
- # Description -- The main function of this routine is to set the "finished"
- # flag so the main event loop will stop looping. I also close
- # all the windows and it's associated items. I know that I don't
- # have to do this because the system will get rid of all the
- # application's memory when it quits, but hey, I like to clean
- # up afterwards.
- #
- # LIST MANAGER SPECIFICS
- # ---- ------- ---------
- # Disposing of the list -- BEFORE closing the window, you must get rid of the
- # list by calling LDispose.
- }
- PROCEDURE DoQuit;
-
- VAR
- errNo: INTEGER; { Returned by FSClose }
- testWindow: WindowPtr; { Frontmost window }
- windPeek: DocumentPeek; { Document record of top window }
- stopLoop: Boolean; { Flag to stop window-closing loop }
-
- BEGIN
- stopLoop := false; { Initialize loop flag }
- testWindow := FrontWindow; { Get the top window }
- windPeek := DocumentPeek(testWindow); { Get the top window's doc record }
- IF testWindow <> NIL THEN { If there is a window active }
- BEGIN
- REPEAT
- LDispose(windPeek^.docList); { Get rid of the list }
- CloseWindow(testWindow); { Get rid of the window }
- testWindow := FrontWindow; { Get the top window, if any }
- IF testWindow <> nil THEN { If there is a window }
- windPeek := DocumentPeek(testWindow) { Get it's doc record }
- ELSE { If there are no more windows }
- stopLoop := true; { Stop looping }
- UNTIL stopLoop;
- END;
- gFinished := TRUE; { If there were no open windows, just stop the application }
- END;
-
- {
- # DoFind -- A List Manager specific routine that searches for data in a cell
- #
- # Called By -- DoFileMenu
- #
- # Description -- This routine puts up a dialog box that the user will type
- # the text to be found into. After the user clicks the OK button,
- # the List Manager routine LSearch to find the cell (if any) that
- # data is located in. Note that theCell must be initialized to
- # (0,0) because the LSearch routine starts searching at theCell.
- }
- PROCEDURE DoFind;
-
- VAR
- theDialog: DialogPtr; { Pointer to the dialog box }
- itemHit: INTEGER; { Item the mouse is clicked in }
- doneDialog: Boolean; { Modal Dialog loop flag }
- theType: INTEGER; { Returned by GetDItem--not used }
- dataLen: INTEGER; { Length of the find text }
- theCell: Cell; { The cell the text is found in }
- item: Handle; { A handle to the dialog editText item }
- box: Rect; { Returned by GetDItem--not used }
- theString: Str255; { The find text }
- dStorage: DialogRecord; { The dialog record }
-
- BEGIN
- theDialog := GetNewDialog(findDlog, @dStorage, DialogPtr(-1)); { Get the dialog }
- doneDialog := false; { Initialize the repeat loop flag }
- REPEAT
- ModalDialog(nil, itemHit); { Get the item the mouse was clicked in }
- CASE (itemHit) OF
- 1: BEGIN { The OK button }
- doneDialog := true; { Stop looping }
- GetDItem(theDialog, 2, theType, item, box); { Get the editText item }
- GetIText(item, theString); { Get the find text }
- dataLen := Length(theString); { Get the length of the text }
- SetPt(theCell, 0, 0); { Initialize the cell }
- IF (LSearch(POINTER(ORD(@theString)+1), dataLen, nil, theCell, gWindInfo^.docList)) THEN
- LSetSelect(true, theCell, gWindInfo^.docList)
- ELSE
- SysBeep(20); { Beep if nothing was found }
- END;
- END; {Case}
- UNTIL doneDialog;
- CloseDialog(theDialog); { Get rid of the dialog }
- END;
-
- {
- # DoFileMenu -- Respond to the user selecting an item in the File Menu
- #
- # Called By -- HandleMenuSelect
- #
- # Description -- This routine is simply a case statement that calls a routine
- # that handles the selected item
- #
- # LIST MANAGER SPECIFICS
- # ---- ------- ---------
- # Adding a row -- When the itemID "AddItem" is passed in the item ID parameter,
- # the case statement simply calls LAddRow to add another row. The
- # rowNum parameter is passed 32767 to ensure that the row is added
- # to the end of the list.
- # Deleting a row -- When the item ID "DeleteItem" is passed in the item ID
- # parameter, the case statement finds which cell (if any) is
- # selected, then calls LDelRow to delete the row the selected
- # cell is in.
- }
- PROCEDURE DoFileMenu(itemID: INTEGER);
-
- VAR
- newRow: INTEGER; { Number of the new row }
- theCell: Cell; { Generic cell variable }
-
- BEGIN
- CASE itemID OF
- NewItem: DoNew; { Get a new list }
-
- CloseItem: DoClose; { Close a list }
-
- AddItem: newRow := LAddRow(1, 32767, gWindInfo^.docList); { Add a new row }
-
- DeleteItem: { Get rid of a new row }
- BEGIN
- SetPt(theCell, 0, 0); { Initialize theCell to the first cell in the list }
- IF (LGetSelect(true, theCell, gWindInfo^.docList)) THEN { If any cell is selected, then }
- LDelRow(1, theCell.v, gWindInfo^.docList); { Delete the row the first selected cell is in }
- END;
-
- FindItem: DoFind; { Find data in a cell }
-
- Quit: DoQuit; { Quit the program }
-
- END;
- HiliteMenu(0);
- END; {DoFileMenu}
-
- {
- # DoEditMenu -- Respond to the user selecting an item from the Edit menu
- #
- # Called By -- HandleMenuSelect
- #
- # Description -- The routine is a case statement that handles all the items
- # in the edit menu.
- #
- # LIST MANAGER SPECIFICS
- # ---- ------- ---------
- # Cutting a cell -- Cut was implemented by using LGetCell to get the data,
- # then calling LClrCell to clear the cell.
- # Copying a cell -- Same as cutting, but LClrCell wasn't called.
- # Pasting a cell -- Paste was implemented by using LSetCell.
- # Clearing a cell -- Clear was implemented by using LClrCell.
- # About LGetSelect -- Before LGetSelect is called, the theCell parameter is
- # initialized to the first cell in the list (0,0). The reason
- # for this is that LGetSelect finds the first cell that is
- # hilighted that is *equal to or greater than* the theCell
- # parameter. Therefore, if you want to find the first cell in
- # the entire list, set the theCell parameter to (0,0).
- }
- PROCEDURE DoEditMenu(itemID: INTEGER);
-
- VAR
- theCell: Cell; { Generic cell variable }
- dataLen: INTEGER; { Length of data in our private scrap }
-
- BEGIN
- IF (gActvWindow <> NIL) THEN { If a window exists, then }
- CASE itemID OF { Find which item was selected }
- UndoItem: ; { There is no undo }
-
- CutItem: { Cut data from a cell }
- BEGIN
- SetPt(theCell, 0, 0); { Initialize theCell to the first item }
- IF (LGetSelect(true, theCell, gWindInfo^.docList)) THEN { Find the cell that is selected }
- BEGIN
- gClipLen := 256; { Initialize the scrap length }
- LGetCell(POINTER(ORD(@gClipboard)+1), gClipLen, theCell, gWindInfo^.docList); { Get the data }
- LClrCell(theCell, gWindInfo^.docList); { Clear the data }
- LDraw(theCell, gWindInfo^.docList); { Redraw the cell }
- END
- ELSE
- SysBeep(20);
- END;
-
- CopyItem: { Copy data from a cell }
- BEGIN
- SetPt(theCell, 0, 0);
- IF (LGetSelect(true, theCell, gWindInfo^.docList)) THEN
- BEGIN
- gClipLen := 256;
- LGetCell(POINTER(ORD(@gClipboard)+1), gClipLen, theCell, gWindInfo^.docList);
- LDraw(theCell, gWindInfo^.docList);
- END
- ELSE
- SysBeep(20);
- END;
-
- ClearItem: { Clear data from the cell }
- BEGIN
- SetPt(theCell, 0, 0);
- IF (LGetSelect(true, theCell, gWindInfo^.docList)) THEN
- BEGIN
- gClipLen := 256;
- LClrCell(theCell, gWindInfo^.docList);
- LDraw(theCell, gWindInfo^.docList);
- END
- ELSE
- SysBeep(20);
- END;
-
- PasteItem: { Paste data into a cell }
- BEGIN
- SetPt(theCell, 0, 0);
- IF (LGetSelect(true, theCell, gWindInfo^.docList)) THEN
- BEGIN
- LSetCell(POINTER(ORD(@gClipboard)+1), gClipLen, theCell, gWindInfo^.docList);
- LDraw(theCell, gWindInfo^.docList);
- END
- ELSE
- SysBeep(20);
- END;
- END;
- HiliteMenu(0);
- END;
-
- {
- # DoListMenu -- Respond to the user selecting an item from the List menu
- #
- # Called By -- HandleMenuSelect
- #
- # Description -- This routine simply checks or unchecks the menu item passed
- # as a parameter. When a new list is created, these menu items
- # are polled to see which flags should be set.
- }
- PROCEDURE DoListMenu(itemID: INTEGER);
-
- VAR
- theMark: CHAR; { Mark returned by GetItemMark }
-
- BEGIN
- GetItemMark(gMenuItem[ListID], itemID, theMark); { Get the mark of the item }
- IF theMark = CHR(checkMark) THEN { If it is a check mark then }
- CheckItem(gMenuItem[ListID], itemID, false) { Uncheck the item }
- ELSE
- CheckItem(gMenuItem[ListID], itemID, true); { Otherwise check it }
- HiliteMenu(0);
- END;
-
- {
- # DoFontMenu -- Respond to a user selecting an item in the Font sub menu
- #
- # Called By -- HandleMenuSelect
- #
- # Description -- When an item is selected, the "old" Font name is unchecked,
- # the new font is set, and it checked in the menu. Then the
- # font name and item global variables are set.
- }
- PROCEDURE DoFontMenu(itemID: INTEGER);
-
- VAR
- theString: Str255; { Name of the font selected }
-
- BEGIN
- CheckItem(gFontSMenu, gFontItem, false); { Uncheck the current font name }
- GetItem(gFontSMenu, itemID, theString); { Get the name of the selected font }
- CheckItem(gFontSMenu, itemID, true); { Check the item }
- gFontName := theString; { Set the global font var }
- gFontItem := itemID; { Set the global item id }
- HiliteMenu(0);
- END;
-
- {
- # DoCellMenu -- Respond to the user selecting an item in the Cell menu
- #
- # Called by -- HandleMenuSelect
- #
- # Description -- This routine sends the itemID to a case statement where it
- # is handled. If the itemID is "IndentItem", then the vertical
- # and horizontal coordinates are retrieved from the dialog box
- # used to ask the user for the coordinates, then sets the indent
- # field of the ListHandle to those coordinates. If itemID is
- # CSizeItem, then the coordinates of the cell size are retrieved
- # from the dialog box, then set by using LCellSize. If itemID is
- # FSizeItem, then the font size entered in the dialog box is
- # set in the txSize field of the grafPort. This change does not
- # take affect until a new list is created.
- }
- PROCEDURE DoCellMenu(itemID: INTEGER);
-
- VAR
- theString: Str255; { String returned by GetIndString/GetIText }
- dStorage: DialogRecord; { Storage for the dialog record }
- theDialog: DialogPtr; { Pointer to the dialog }
- theType: INTEGER; { Not used--passed to GetDItem }
- item: Handle; { Handle to item, returned by GetDItem }
- box: Rect; { Not used--passed to GetDItem }
- origIndent: Point; { Data indent before changing }
- vertIndent: LONGINT; { Vertical indentation set by user }
- horizIndent: LONGINT; { Horizontal indentation set by user }
- itemHit: INTEGER; { Item number returned by ModalDialog }
- doneDialog: Boolean; { Flag is set when user is done with dialog }
- vertItem: Handle; { Handle to vertical indent. text box }
- horizItem: Handle; { Handle to horizontal indent. text box }
-
- BEGIN
- doneDialog := false; { Initialize the doneDialog flag }
- CASE itemID OF
- IndentItem: { Set the indent field of the List Handle }
- BEGIN
- IF (gActvWindow <> NIL) THEN { If a window is present }
- BEGIN
- { Draw a dialog and set the editText items }
- theDialog := GetNewDialog(cellDlog, @dStorage, DialogPtr(-1));
- GetDItem(theDialog, 4, theType, item, box);
- GetIndString(theString, theStrList, vertInd);
- SetIText(item, theString);
- GetDItem(theDialog, 5, theType, item, box);
- GetIndString(theString, theStrList, horizInd);
- SetIText(item, theString);
- GetDItem(theDialog, 6, theType, item, box);
- GetIndString(theString, theStrList, indentInd);
- SetIText(item, theString);
- origIndent := gWindInfo^.docList^^.indent;
- vertIndent := origIndent.v;
- horizIndent := origIndent.h;
- GetDItem(theDialog, 2, theType, vertItem, box);
- NumToString(vertIndent, theString);
- SetIText(vertItem, theString);
- GetDItem(theDialog, 3, theType, horizItem, box);
- NumToString(horizIndent, theString);
- SetIText(horizItem, theString);
- ShowWindow(theDialog);
- REPEAT
- { When an event occurs, check if the OK button was hit }
- ModalDialog(nil, itemHit);
- CASE itemHit OF
- 1: BEGIN
- { If the OK button was hit, get the editText items, and set the indent field }
- doneDialog := true;
- GetIText(vertItem, theString);
- StringToNum(theString, vertIndent);
- GetIText(horizItem, theString);
- StringToNum(theString, horizIndent);
- SetPt(origIndent, LoWord(horizIndent), LoWord(vertIndent));
- gWindInfo^.docList^^.indent := origIndent;
- LUpdate(gActvWindow^.visRgn, gWindInfo^.docList);
- END;
- END;
- UNTIL doneDialog;
- CloseDialog(theDialog);
- END
- ELSE
- SysBeep(20);
- END;
-
- CSizeItem: { Set the cell size }
- BEGIN
- IF (gActvWindow <> NIL) THEN { IF there is a window }
- BEGIN
- { Draw the dialog and set editText items }
- theDialog := GetNewDialog(cellDlog, @dStorage, DialogPtr(-1));
- GetDItem(theDialog, 4, theType, item, box);
- GetIndString(theString, theStrList, vertInd);
- SetIText(item, theString);
- GetDItem(theDialog, 5, theType, item, box);
- GetindSTring(theString, theStrList, horizInd);
- SetIText(item, theString);
- GetDItem(theDialog, 6, theType, item, box);
- GetIndString(theString, theStrList, cSizeInd);
- SetIText(item, theString);
- origIndent := gWindInfo^.docList^^.cellSize;
- vertIndent := origIndent.v;
- horizIndent := origIndent.h;
- GetDItem(theDialog, 2, theType, vertItem, box);
- NumToString(vertIndent, theString);
- SetIText(vertItem, theString);
- GetDItem(theDialog, 3, theType, horizItem, box);
- NumToString(horizIndent, theString);
- SetIText(horizItem, theString);
- ShowWindow(theDialog);
- REPEAT
- ModalDialog(nil, itemHit);
- CASE itemHit OF
- 1: BEGIN
- { IF the OK button was hit, get the editText items the user set,
- and call LCellSize to change the cell size }
- doneDialog := true;
- GetIText(vertItem, theString);
- StringToNum(theString, vertIndent);
- GetIText(horizItem, theString);
- StringToNum(theString, horizIndent);
- SetPt(origIndent, LoWord(horizIndent), LoWord(vertIndent));
- LCellSize(origIndent, gWindInfo^.docList);
- END;
- END;
- UNTIL doneDialog;
- CloseDialog(theDialog);
- END
- ELSE
- SysBeep(20);
- END;
-
- FSizeItem: { Set the font size }
- BEGIN
- theDialog := GetNewDialog(fontSDlog, @dStorage, DialogPtr(-1));
- GetDItem(theDialog, 2, theType, item, box);
- SetIText(item, '10');
- ShowWindow(theDialog);
- REPEAT
- ModalDialog(nil, itemHit);
- CASE itemHit OF
- 1: BEGIN
- { IF the OK button was hit, get the editText item and set the font size }
- doneDialog := true;
- GetIText(item, theString);
- StringToNum(theString, horizIndent);
- gFontSize := LoWord(horizIndent);
- END;
- END; {case}
- UNTIL doneDialog;
- CloseDialog(theDialog);
- END;
- END;
- HiliteMenu(0);
- END;
-
- {
- # HandleMenuSelect -- Determines which menu was selected from
- #
- # Called By -- HandleMouseDown/HandleKeyDown
- #
- # Description -- This routines finds the menuID and itemID of the item
- # selected by the user. The menu information is passed in the
- # parameter menuInfo. The high-order word contains the menuID
- # and the low-order word holds the itemID. These items are
- # extracted by using HiWord and LoWord, respectively. The menuID
- # is sent to a case statement which calls a routine that handles
- # that menu.
- }
- PROCEDURE HandleMenuSelect(menuInfo: LONGINT);
-
- VAR
- menuID: INTEGER; { Menu's resource ID }
- itemID: INTEGER; { Item's position in menu }
-
- BEGIN
- menuID := HiWord(menuInfo); { Get the selected menu ID }
- itemID := LoWord(menuInfo); { Get the item ID }
-
- IF menuID <> 0 THEN { if MenuSelect returns a 0 in the high order integer,
- it means that the mouse was released outside the menu }
- CASE menuID OF
-
- AppleMenu: DoAppleMenu(itemID);
-
- FileMenu: DoFileMenu(itemID);
-
- EditMenu: DoEditMenu(itemID);
-
- ListMenu: DoListMenu(itemID);
-
- CellMenu: DoCellMenu(itemID);
-
- FontSMenu: DoFontMenu(itemID);
- END;
- END;
-
- {
- # HandleContent -- Respond to a mouse event inside a window
- #
- # Called By -- HandleMouseDown
- #
- # Description -- When a mouse-down event occurs in the content portion of a
- # window (when FindWindow returns inContent), the application must
- # take appropriate action:
- # 1. Make The Window Active - If the window passed in the
- # whichWindow parameter is not the active window, then
- # it must be made active by calling SelectWindow.
- # The global window pointer and document record must
- # reflect the changes.
- # 2. If the window is already active, you need to find if
- # the click occurred inside an object in the window
- # such as a TextEdit box, control, or indicator. Note
- # that the TextEdit, Control and List Managers
- # (among others) require the mouse down loaction in
- # local coordinates, so the routine GlobalToLocal
- # is called to get the local point coordinates.
- #
- # LIST MANAGER SPECIFICS
- # ---- ------- ---------
- # Click occurs in the list -- A check must be made to see if the mouse down
- # occurred in the list. You do this by getting the list rect
- # from the rView field in the ListHandle and calling PtInRect.
- # Remember that rView returns the rect coordinates in the LOCAL
- # coordinate system, so the point returned by GlobalToLocal
- # should be used.
- # If the mouse down was in the list, then call the List
- # Manager routine LClick. This routine will handle any actions
- # needed in the list (selecting, moving scroll bars) according
- # to the list definition procedure (LDEF).
- # IMPORTANT NOTE: The rView rectangle DOES NOT include the
- # scroll bars. Before using PtInRect to find if the click
- # occurred in the list, add 15 to the bottom and right fields of
- # the rect to include the scroll bars. If you don't do this, the
- # list will not scroll.
- }
- PROCEDURE HandleContent(whichWindow :WindowPtr);
-
- VAR
- thePoint: Point; { events.where in local coordinates }
- theRect: Rect; { The area the list occupies }
- yorn: BOOLEAN; { Junk result from LClick }
-
- BEGIN
- gActvWindow := FrontWindow; { Get the frontmost window }
- thePoint := gEvents.where; { Set up a point to be converted to local coords }
- GlobalToLocal(thePoint); { Convert to local coordinates }
- IF whichWindow <> gActvWindow THEN { If the window selected in not the front window }
- BEGIN
- SelectWindow(whichWindow); { Select it }
- gActvWindow := whichWindow; { Set the new active window }
- gWindInfo := DocumentPeek(gActvWindow); { Set the window information }
- END;
- IF gWindInfo^.docList^ <> nil THEN { If the list is active }
- BEGIN
- theRect := gWindInfo^.docList^^.rView; { Get the rectangle of the list }
- theRect.right := theRect.right + 15; { Account for the vertical and }
- theRect.bottom := theRect.bottom + 15; { horizontal scroll bars }
- IF PtInRect(thePoint, theRect) THEN { If the mouse click was in the list rectangle, then }
- yorn := LClick(thePoint, gEvents.modifiers, gWindInfo^.docList) { Tell the list it was clicked in }
- END;
- END;
-
- {
- # HandleGrow -- Respond to a mouse down event in the grow icon
- #
- # Called by -- HandleMouseDown
- #
- # Description -- When a mouse down event occurs in the grow icon (when
- # FindWindow returns inGrow) the application must grow the
- # window, following the movements of the mouse. This i
- # this is accomplished by calling GrowWindow, which returns the
- # new width and height of the window (or 0 if no change was
- # made). The width is in the low-order word of the long result
- # and the height is in the high-order word. These values are
- # extracted using LoWord and HiWord. After getting this result,
- # SizeWindow is called, passing the height and width returned by
- # GrowWindow. After this is done, the window is marked as "dirty"
- # and updated by calling InvalRect.
- #
- # LIST MANAGER SPECIFICS
- # ---- ------- ---------
- # Growing the list -- You can use the height and width values returned by
- # GrowWindow in the ListManager routine LSize, remembering to
- # subtract room for the scroll bars, if any.
- }
- PROCEDURE HandleGrow(whichWindow: WindowPtr);
-
- VAR
- windSize: LONGINT; { Gets the new size of a window when it is grown }
- vert: INTEGER; { The vertical component of the growth in windSize }
- horiz: INTEGER; { The horizontal component of the growth in windSize }
-
- BEGIN
- windSize := GrowWindow(whichWindow,gEvents.where,gGrowArea); { Grow the window }
- vert := HiWord(windSize); { Get the vertical displacement }
- horiz := LoWord(windSize); { Get the horizontal displacement }
- SizeWindow(whichWindow,horiz,vert,TRUE); { Make the changes to the window }
- LSize(horiz-15, vert-15, gWindInfo^.docList);{ Make the changes to the list }
- InvalRect(whichWindow^.portRect); { Get the new window ready for updating }
- END;
-
- {
- # HandleMouseDown -- Take care of a mouse-down event.
- #
- # Called by -- Main program
- #
- # Description -- The major block of the program is a case statement that
- # branches to the constant returned by the window manager
- # function FindWindow. Most of the events are handled inside the
- # case statement; a few have external routines. The routines
- # that are called from this routine are:
- # HandleMenuSelect (inMenuBar)
- # HandleContent (inContent)
- # HandleGrow (inGrow)
- }
- PROCEDURE HandleMouseDown;
-
- VAR
- whichWindow: WindowPtr; { Pointer to window returned by FindWindow }
- windPeek: DocumentPeek; { Information about window }
- menuInfo: LONGINT; { Menu information returned by MenuSelect }
- dPartCode: INTEGER; { Part code returned by FindWindow }
- width: INTEGER; { Vertical change made by zooming }
- height: INTEGER; { Horizontal change made by zooming }
- zoomRect: Rect; { Window rect after zooming }
-
- BEGIN
- dPartCode := FindWindow(gEvents.where, whichWindow); { Find which part of the window the click occurred in }
-
- CASE dPartCode OF
- inMenuBar: { Click in the menu bar }
- BEGIN
- menuInfo := MenuSelect(gEvents.where); { Get menuID, itemID }
- HandleMenuSelect(menuInfo);
- END;
-
- inContent: HandleContent(whichWindow); { Click in the content region }
-
- inDrag: { Click in the drag region }
- BEGIN
- DragWindow(whichWindow,gEvents.where,gDragArea);
- END;
-
- inGrow: HandleGrow(whichWindow); { Click in grow (lower left corner) box }
-
- inGoAway: { Click in the go away box }
- BEGIN
- IF TrackGoAway(whichWindow,gEvents.where) THEN
- DoClose;
- END;
-
- inSysWindow: SystemClick(gEvents,whichWindow); { Click in desktop or DA }
-
- inZoomIn, inZoomOut: { Click in zoom box }
- BEGIN
- IF TrackBox(whichWindow,gEvents.where,dPartCode) THEN { If the mouse was pressed and released in the zoom box }
- BEGIN
- windPeek := DocumentPeek(whichWindow);
- ZoomWindow(whichWindow,dPartCode,TRUE); { Zoom the window in, or out, depending upon value of inout }
- zoomRect := whichWindow^.portRect;
- width := zoomRect.right - zoomRect.left;
- height := zoomRect.bottom - zoomRect.top;
- LSize(width-15, height-15, windPeek^.docList);
- InvalRect(whichWindow^.portRect); { Mark the window as needing an update }
- END;
- END;
- END; {case FindWindow}
- END; { CASE mouseDown }
-
- {
- # HandleUpdateEvt -- Do a window update
- #
- # Called by -- main event loop
- #
- # Description -- When GetNextEvent returns updateEvt, this routine is called
- # to redraw the contents of a window.
- #
- # LIST MANAGER SPECIFICS
- # ---- ------- ---------
- # LUpdate -- The List Manager routine LUpdate is called to re-draw the window
- # that needs updating.
- }
- PROCEDURE HandleUpdateEvt;
-
- VAR
- yorn: INTEGER; { FOR loop control variable }
- theWindow: WindowPtr; { Window to be updated }
- theList: DocumentPeek; { Information about the window }
- savePort: GrafPtr; { Active port when called }
-
- BEGIN
- theWindow := WindowPtr(gEvents.message); { Get the window referenced by the event by coercing it }
- theList := DocumentPeek(theWindow);
- GetPort(savePort); { save the current port }
- SetPort(theWindow); { set the port to the updated window }
- BeginUpdate(theWindow); { Starting the update }
- EraseRect(theWindow^.portRect); { Erase the window }
- LUpdate(theWindow^.visRgn, theList^.docList); { Update the List }
- DrawGrowIcon(theWindow); { Draw the grow icon }
- EndUpdate(theWindow); { Ending the update }
- SetPort(SavePort); { Restoring the port }
-
- END;
-
- {
- # HandleActivateEvt -- Make a window active, deactivate another window
- #
- # Called by -- main event loop
- #
- # Description -- When an activate event is needed, GetNextEvent returns
- # activateEvt, plus a flag in the modifiers field. If the flag
- # is an activate flag (bit 0 is 1 -- see Inside Mac), then
- # a grow icon (if any) is drawn, and scroll bars (if any) are
- # made active. If the flag is a deactivate flag (bit 0 is 0),
- # then the grow icon is erased and any scroll bars are inactivated.
- #
- # LIST MANAGER SPECIFICS
- # ---- ------- ---------
- # LActivate -- The list manager routine LActivate is called to make a list
- # either active or inactive.
- }
- PROCEDURE HandleActivateEvt;
-
- VAR
- theWindow: WindowPtr; { Window that is active/inactive }
- windPeek: DocumentPeek; { Information about the window }
- invH: Rect; { Grow icon to be erased }
- dActivate: Boolean; { True if activate, false if inactive }
-
- BEGIN
- theWindow := WindowPtr(gEvents.message); { Get the window pointer from the event
- record, and coerce it into a window pointer }
- windPeek := DocumentPeek(theWindow);
- dActivate := Odd(gEvents.modifiers); { Get the modifiers field from the event
- record. A 1 denotes activation, 0 deactivation }
- if dActivate THEN { If it is an activate event, then }
- BEGIN
- SetPort(theWindow); { Set the current grafPort }
- gActvWindow := theWindow; { Make it the active window }
- LActivate(true, windPeek^.docList);
- DrawGrowIcon(theWindow);
- END
- ELSE { If it is a deactivate event, then }
- BEGIN
- LActivate(false, windPeek^.docList);
- SetRect(invH, theWindow^.portRect.right - 14,
- theWindow^.portRect.bottom - 14,
- theWindow^.portRect.right,
- theWindow^.portRect.bottom);
- EraseRect(invH);
- END;
- END;
-
- {
- # HandleKeyDown -- Respond to a key being pressed.
- #
- # Called by -- main event loop
- #
- # Description -- There are several special cases to be checked for this
- # routine. If the command key is depressed when the key is down,
- # then the key down event is a command key equivalent, and the
- # character that represents the key is passed to the Menu Manager
- # routine MenuKey.
- # If the command key is not pressed, then the character should be
- # passed to the application. There are several non-printin keys
- # that need to be handled specially. These keys are the carrriage
- # return (13), tab (9), backspace (8), and enter (3). If the key
- # pressed wansn't any of these keys, then the character should be
- # sent to the application.
- #
- # LIST MANAGER SPECIFICS
- # ---- ------- ---------
- # The following special cases are handled in the following way:
- # CR -- Advance one row in same column
- # Tab -- Advance one column in the same row. If the current cell is the
- # last cell in the row, then go to the first column in the next row.
- # (For more information on how CR's and tabs are handled, see the
- # description of LNextCell in the List Manager chapter of Inside
- # Macintosh.)
- # Backspace -- Delete data in the cell
- # Enter -- Unselect the currently selected cell.
- # Any printing character -- add the character to the data for the cell.
- }
- PROCEDURE HandleKeyDown(modifiers: INTEGER);
-
- VAR
- theKey: STRING[1]; { The key that was depreseed (char format) }
- theCell: Cell; { Generic cell variable }
- dataLen: INTEGER; { Length of data in cell }
- CP: Ptr; { Pointer to data }
- menuInfo: LONGINT; { Returned by menu key }
-
- BEGIN
- IF BitAnd(modifiers,cmdKey) = cmdKey THEN { If the command (apple) key was pressed down }
- BEGIN { then a menu equivalent was pressed }
- menuInfo := MenuKey(CHR(BitAnd(gEvents.message,charCodeMask)));
- HandleMenuSelect(menuInfo);
- END
- ELSE
- BEGIN { Otherwise handle the character }
- SetPt(theCell, 0, 0);
- IF (LGetSelect(true, theCell, gWindInfo^.docList)) tHEN
- BEGIN
- CASE BitAnd(gEvents.message, charCodeMask) OF
- 13: BEGIN { Carriage return pressed }
- LSetSelect(false, theCell, gWindInfo^.docList);
- IF (LNextCell(false, true, theCell, gWindInfo^.docList)) THEN
- LSetSelect(true, theCell, gWindInfo^.docList)
- ELSE
- BEGIN
- theCell.v := 0;
- LSetSelect(true, theCell, gWindInfo^.docList);
- END;
- END;
-
- 9: BEGIN { Tab pressed }
- LSetSelect(false, theCell, gWindInfo^.docList);
- IF (LNextCell(true, true, theCell, gWindInfo^.docList)) THEN
- LSetSelect(true, theCell, gWindInfo^.docList)
- ELSE
- BEGIN
- theCell.v := 0;
- LSetSelect(true, theCell, gWindInfo^.docList);
- END;
- END;
-
- 8: BEGIN { Backspace pressed }
- dataLen := 256;
- CP := NewPtr(256);
- LGetCell(CP, dataLen, theCell, gWindInfo^.docList);
- IF dataLen <> 0 THEN
- LSetCell(CP, dataLen-1, theCell, gWindInfo^.docList);
- DisposPtr(CP);
- END;
-
- 3: BEGIN { Enter pressed }
- LSetSelect(false, theCell, gWindInfo^.docList);
- END;
-
- OTHERWISE { It was a printing character }
- BEGIN
- theKey[1] := CHR(BitAnd(gEvents.message, charCodeMask));
- LAddToCell(POINTER(ORD(@theKey)+1), 1, theCell, gWindInfo^.docList);
- LDraw(theCell, gWindInfo^.docList);
- END;
- END;
- END;
- END;
- END;
-
- PROCEDURE _DataInit; EXTERNAL;
-
- {
- # The Main Program
- #
- # Called by -- The entry point
- #
- # Description -- The main program is used to initialize any variables and
- # data structures. After this, the program enters an "event
- # loop". The event loop calls SystemTask, which handles DA's and
- # other system necessities, then calls GetNextEvent, which returns
- # an event constant when an event occurs.
- }
- BEGIN {main}
-
- UnloadSeg(@_DataInit);
- Initialize; { Start initialization }
-
- repeat { THE START OF THE MAIN LOOP }
- SystemTask; { Handle DA's and VBL tasks }
- IF GetNextEvent(everyEvent,gEvents) THEN { if there is an event--every event is a mask for
- all events, as some events may be masked out so
- they are not recognized. }
- BEGIN
- CASE gEvents.what OF
- mouseDown: HandleMouseDown;
- { the mouse was pressed }
- keyDown: HandleKeyDown(gEvents.modifiers);
- { a key was pressed }
- autoKey:;
- { a key was pressed and continues to be held down }
- updateEvt: HandleUpdateEvt;
- { an update event was triggered }
- activateEvt: HandleActivateEvt;
- { a window was opened or made active }
- END; {case}
- END;
- UNTIL gFinished; { Th-th-th-that's all folks }
- END.
-